use std::fmt::Debug;

use serde::{de::DeserializeOwned, Deserialize, Serialize};
use thiserror::Error;

use crate as honeybee;
use crate::prelude::*;

pub trait MessageId {
    const ID: u16;
}

pub trait HoneybeeMessage:
    'static + MessageId + Serialize + DeserializeOwned + Debug + Send + Sync
{
}

impl<T> HoneybeeMessage for T where
    T: 'static + MessageId + Serialize + DeserializeOwned + Debug + Send + Sync
{
}

pub trait Payload: Sized {
    fn serialize(&self) -> Result<bytes::Bytes, std::io::Error>;
    fn deserialize(data: bytes::Bytes) -> Result<Self, Box<dyn std::error::Error>>;
    fn size(&self) -> u16;
}

#[derive(Serialize, Deserialize, Error, Debug)]
pub enum RpcResponseError {
    #[error("rpc timeout after {0}ms")]
    RpcTimeOut(u128),
    #[error("RpcError:{0}")]
    RpcError(String),
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RpcResponse<R>(pub Result<R, RpcResponseError>);

pub trait RpcResult: 'static + Serialize + DeserializeOwned + Debug + Send + Sync {}

impl<R> RpcResult for R where R: 'static + Serialize + DeserializeOwned + Debug + Send + Sync {}

impl<R> MessageId for RpcResponse<R> {
    const ID: u16 = 65535;
}

#[netmessage(id = 65534)]
pub struct UserMessageForward {
    pub uid: i64,
    pub msg_id: u16,
    pub bytes: Vec<u8>,
}

#[netmessage(id = 65533)]
#[derive(Clone)]
pub struct AllUserMessageForward {
    pub msg_id: u16,
    pub bytes: Vec<u8>,
}

#[netmessage(id = 65532)]
pub struct UserMessageApp {
    pub uid: i64,
    pub msg_id: u16,
    pub bytes: Vec<u8>,
}

#[netmessage(id = 65531)]
#[derive(Clone)]
pub struct AllUserMessageApp {
    pub msg_id: u16,
    pub bytes: Vec<u8>,
}

#[netmessage(id = 65530)]
pub struct TcpRegister {
    pub node_type: String,
    pub node_name: String,
}

impl TcpRegister {
    pub fn new(node_type: &str, node_name: &str) -> Self {
        Self {
            node_type: node_type.into(),
            node_name: node_name.into(),
        }
    }
}

#[netmessage(id = 65529)]
pub struct UmsgForward {
    pub uid: i64,
    pub msg_type: umsg_db::UmsgType,
    pub msg_bytes: Vec<u8>,
}

#[netmessage(id = 65528)]
pub struct GmsgForward {
    pub msg_type: gmsg_db::GmsgType,
    pub msg_bytes: Vec<u8>,
    pub expire: Option<i64>,
}
